package org.aceor.mddal.gateway.resultset;

import org.aceor.mddal.common.sqlparser.result.object.Limit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.List;

/**
 * Created by lxue on 16/4/16.
 */
public abstract class BaseResultSet extends AbstractResultSetAdapter implements ResultSet {
    private static final Logger log = LoggerFactory.getLogger(BaseResultSet.class);

    private final List<ResultSet> resultSets;

    private boolean closed;

    private final Limit limit;

    private boolean offsetSkipped;

    private int readCount;

    public BaseResultSet(List<ResultSet> resultSets, Limit limit) {
        this.resultSets = resultSets;
        this.limit = limit;
        setCurrentResultSet(resultSets.get(0));
    }

    public List<ResultSet> getResultSets() {
        return resultSets;
    }

    @Override
    public final boolean next() throws SQLException {
        if (null != limit && !offsetSkipped) {
            skipOffset();
        }
        return null == limit
                ? nextRowSet()
                : ++readCount <= limit.getRowCount() && nextRowSet();
    }

    private void skipOffset() {
        for (int i = 0; i < limit.getOffset(); i++) {
            try {
                if (!nextRowSet()) {
                    break;
                }
            } catch (final SQLException ignored) {
                log.warn("Skip result set error", ignored);
            }
        }
        offsetSkipped = true;
    }

    /**
     * 迭代结果集.
     *
     * @return true 可以继续访问 false 不能继续访问
     * @throws SQLException
     */
    protected abstract boolean nextRowSet() throws SQLException;

    @Override
    public final void close() throws SQLException {
        for (ResultSet each : resultSets) {
            each.close();
        }
        closed = true;
    }

    @Override
    public final boolean isClosed() throws SQLException {
        return closed;
    }

    @Override
    public final boolean wasNull() throws SQLException {
        return getCurrentResultSet().wasNull();
    }

    @Override
    public final int getFetchDirection() throws SQLException {
        return getCurrentResultSet().getFetchDirection();
    }

    @Override
    public final void setFetchDirection(final int direction) throws SQLException {
        for (ResultSet each : resultSets) {
            each.setFetchDirection(direction);
        }
    }

    @Override
    public final int getFetchSize() throws SQLException {
        return getCurrentResultSet().getFetchSize();
    }

    @Override
    public final void setFetchSize(final int rows) throws SQLException {
        for (ResultSet each : resultSets) {
            each.setFetchSize(rows);
        }
    }

    @Override
    public final int getType() throws SQLException {
        return getCurrentResultSet().getType();
    }

    @Override
    public final int getConcurrency() throws SQLException {
        return getCurrentResultSet().getConcurrency();
    }

    @Override
    public final Statement getStatement() throws SQLException {
        return getCurrentResultSet().getStatement();
    }

    @Override
    public final SQLWarning getWarnings() throws SQLException {
        return getCurrentResultSet().getWarnings();
    }

    @Override
    public final void clearWarnings() throws SQLException {
        getCurrentResultSet().clearWarnings();
    }

    @Override
    public final ResultSetMetaData getMetaData() throws SQLException {
        return getCurrentResultSet().getMetaData();
    }

    @Override
    public final int findColumn(final String columnLabel) throws SQLException {
        return getCurrentResultSet().findColumn(columnLabel);
    }
}
